package cn.ybk.basic.service.impl;

import cn.ybk.basic.constant.RegisterCons;
import cn.ybk.basic.dto.EmailDto;
import cn.ybk.basic.dto.EmailRegisterFormDto;
import cn.ybk.basic.service.EmailCodeService;
import cn.ybk.basic.util.BusinessException;
import cn.ybk.basic.util.EmailUtil;
import cn.ybk.basic.util.SendSmsUtil;
import cn.ybk.basic.util.StrUtils;
import cn.ybk.user.domain.Logininfo;
import cn.ybk.user.domain.User;
import cn.ybk.user.mapper.LogininfoMapper;
import cn.ybk.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class EmailCodeServiceImpl implements EmailCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LogininfoMapper logininfoMapper;

    // 发送邮箱验证码
    @Override
    public void emailCode(EmailRegisterFormDto dto) {
        // 校验数据
        verify(dto);
        // 发送邮件
        sendEmail(dto);
    }

    // 注册
    @Override
    public void emailRegister(EmailDto dto) {
        // 校验数据
        verify(dto);
        // 添加到数据库
        save(dto);

    }

    private void save(EmailDto dto) {
        // 添加数据库
        User user = dto.getUser();
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user, logininfo);
        logininfo.setType(1);
        logininfo.setDisable(true);
        logininfoMapper.add(logininfo);
        user.setLogininfoId(logininfo.getId());
        userMapper.add(user);
    }

    private void verify(EmailDto dto) {
        // 注解@Noblank 校验参数
        // 验证码是否正常
        String emailCode = (String) redisTemplate.opsForValue().get(String.format(RegisterCons.REGISTER_CODE_KEY, dto.getEmail()));
        if (StringUtils.isBlank(emailCode) || !emailCode.equals(dto.getEmailCode())) {
            throw new BusinessException("验证码错误");
        }
        // 密码是否相同
        if (!dto.getEmailPassword().equals(dto.getEmailPasswordRepeat())) {
            throw new BusinessException("两次密码不一致");
        }
        // 邮箱是否注册
        String email = dto.getEmail();
        User userEmail = userMapper.findByEmail(email);
        if (userEmail != null) {
            throw new BusinessException("该邮箱已经被注册过，请重新注册~！");
        }
    }

    private void sendEmail(EmailRegisterFormDto dto) {
        // 判断email验证码两次发送时间是否大于60秒
        Long expire = redisTemplate.getExpire(String.format(RegisterCons.REGISTER_CODE_KEY, dto.getEmail()));
        if (expire > (RegisterCons.CODE_TIME - 1 * 60L)) {
            throw new BusinessException("已经发送邮件，60s内请勿在点击");
        }
        // 是否需要重新生成验证码
        String EmailAgain = (String) redisTemplate.opsForValue().get(dto.getEmail());
        if (StringUtils.isBlank(EmailAgain)) {
            EmailAgain = StrUtils.getRandomString(6);
        }
        log.info("验证码为：{}", EmailAgain);
        // 将验证码存入redis中
        redisTemplate.opsForValue().set(String.format(RegisterCons.REGISTER_CODE_KEY, dto.getEmail()), EmailAgain,
                RegisterCons.CODE_TIME, TimeUnit.SECONDS);
//        // 发送邮箱
//        EmailUtil.sendEmail(email,
//                "3533670493@qq.com",
//                email,
//                "cyuekqvrgrxxdbif",
//                "验证码",
//                EmailAgain);
    }

    private void verify(EmailRegisterFormDto dto) {
        // 注解@Noblank 校验参数
        // 校验图形验证码是否正确
        // 获取在redis中的EmailImageCodeValue中能够获取到图形验证码的值
        String EmailImage = (String) redisTemplate.opsForValue().get(dto.getEmailImageCodeKey());
        if (StringUtils.isBlank(EmailImage) || !EmailImage.equalsIgnoreCase(dto.getEmailImageCodeValue())) {
            throw new BusinessException("图形验证码错误");
        }
        // email是否注册过
        String email = dto.getEmail();
        User user = userMapper.findByEmail(email);
        if (user != null) {
            throw new BusinessException("该邮箱已经被注册过，请重新注册~！");
        }
    }
}
